<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd">
<html lang="zh-CN"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><meta http-equiv="Content-Language" content="zh-CN"><link href="stylesheet.css" media="all" rel="stylesheet" type="text/css">
<title>时间/日期函数和操作符</title>
<script> var _hmt = _hmt || []; (function() { var hm = document.createElement("script"); hm.src = "https://hm.baidu.com/hm.js?d286c55b63a3c54a1e43d10d4c203e75"; var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(hm, s); })(); </script>
</head><body class="SECT1">
<div>
<table summary="Header navigation table" width="100%" border="0" cellpadding="0" cellspacing="0">
<tr><th colspan="5" align="center" valign="bottom">PostgreSQL 8.2.3 中文文档</th></tr>
<tr><td width="10%" align="left" valign="top"><a href="functions-formatting.html" accesskey="P">后退</a></td><td width="10%" align="left" valign="top"><a href="functions.html">快退</a></td><td width="60%" align="center" valign="bottom">章9. 函数和操作符</td><td width="10%" align="right" valign="top"><a href="functions.html">快进</a></td><td width="10%" align="right" valign="top"><a href="functions-geometry.html" accesskey="N">前进</a></td></tr>
</table>
<hr align="LEFT" width="100%"></div>
<div class="SECT1"><h1 class="SECT1"><a name="FUNCTIONS-DATETIME">9.9. 时间/日期函数和操作符</a></h1>
<p><a href="functions-datetime.html#FUNCTIONS-DATETIME-TABLE">表9-26</a>显示了 PostgreSQL 里可以用于处理日期/时间数值的函数，随后一节里描述了细节。<a href="functions-datetime.html#OPERATORS-DATETIME-TABLE">表9-25</a>演示了基本算术操作符的行为。而与格式化相关的函数，可以参考<a href="functions-formatting.html">节9.8</a>。你应该很熟悉<a href="datatype-datetime.html">节8.5</a>的日期/时间数据类型的背景知识。</p>
<p>所有下述函数和操作符接收的 <tt class="TYPE">time</tt> 或 <tt class="TYPE">timestamp</tt> 输入实际上都来自两种可能：一种是接收 <tt class="TYPE">time with time zone</tt> 或 <tt class="TYPE">timestamp with time zone</tt> ，另外一种是接收 <tt class="TYPE">time without time zone</tt> 或 <tt class="TYPE">timestamp without time zone</tt> 。出于简化考虑，这些变种没有独立显示出来。还有，<tt class="LITERAL">+</tt> 和 <tt class="LITERAL">*</tt> 操作符都是以可交换的操作符对(比如，date + integer 和 integer + date)；我们只显示了这样的交换操作符对中的一个。</p>
<div class="TABLE"><a name="OPERATORS-DATETIME-TABLE"></a>
<p><b>表9-25. 日期/时间操做符</b></p>
<table border="1" class="CALSTABLE"><col><col><col>
<thead>
<tr><th>操作符</th><th>例子</th><th>结果</th></tr>
</thead>
<tbody>
<tr><td><tt class="LITERAL">+</tt></td><td><tt class="LITERAL">date '2001-09-28' + integer '7'</tt></td><td><tt class="LITERAL">date '2001-10-05'</tt></td></tr>
<tr><td><tt class="LITERAL">+</tt></td><td><tt class="LITERAL">date '2001-09-28' + interval '1 hour'</tt></td><td><tt class="LITERAL">timestamp '2001-09-28 01:00:00'</tt></td></tr>
<tr><td><tt class="LITERAL">+</tt></td><td><tt class="LITERAL">date '2001-09-28' + time '03:00'</tt></td><td><tt class="LITERAL">timestamp '2001-09-28 03:00:00'</tt></td></tr>
<tr><td><tt class="LITERAL">+</tt></td><td><tt class="LITERAL">interval '1 day' + interval '1 hour'</tt></td><td><tt class="LITERAL">interval '1 day 01:00:00'</tt></td></tr>
<tr><td><tt class="LITERAL">+</tt></td><td><tt class="LITERAL">timestamp '2001-09-28 01:00' + interval '23 hours'</tt></td><td><tt class="LITERAL">timestamp '2001-09-29 00:00:00'</tt></td></tr>
<tr><td><tt class="LITERAL">+</tt></td><td><tt class="LITERAL">time '01:00' + interval '3 hours'</tt></td><td><tt class="LITERAL">time '04:00:00'</tt></td></tr>
<tr><td><tt class="LITERAL">-</tt></td><td><tt class="LITERAL">- interval '23 hours'</tt></td><td><tt class="LITERAL">interval '-23:00:00'</tt></td></tr>
<tr><td><tt class="LITERAL">-</tt></td><td><tt class="LITERAL">date '2001-10-01' - date '2001-09-28'</tt></td><td><tt class="LITERAL">integer '3'</tt></td></tr>
<tr><td><tt class="LITERAL">-</tt></td><td><tt class="LITERAL">date '2001-10-01' - integer '7'</tt></td><td><tt class="LITERAL">date '2001-09-24'</tt></td></tr>
<tr><td><tt class="LITERAL">-</tt></td><td><tt class="LITERAL">date '2001-09-28' - interval '1 hour'</tt></td><td><tt class="LITERAL">timestamp '2001-09-27 23:00:00'</tt></td></tr>
<tr><td><tt class="LITERAL">-</tt></td><td><tt class="LITERAL">time '05:00' - time '03:00'</tt></td><td><tt class="LITERAL">interval '02:00:00'</tt></td></tr>
<tr><td><tt class="LITERAL">-</tt></td><td><tt class="LITERAL">time '05:00' - interval '2 hours'</tt></td><td><tt class="LITERAL">time '03:00:00'</tt></td></tr>
<tr><td><tt class="LITERAL">-</tt></td><td><tt class="LITERAL">timestamp '2001-09-28 23:00' - interval '23 hours'</tt></td><td><tt class="LITERAL">timestamp '2001-09-28 00:00:00'</tt></td></tr>
<tr><td><tt class="LITERAL">-</tt></td><td><tt class="LITERAL">interval '1 day' - interval '1 hour'</tt></td><td><tt class="LITERAL">interval '1 day -01:00:00'</tt></td></tr>
<tr><td><tt class="LITERAL">-</tt></td><td><tt class="LITERAL">timestamp '2001-09-29 03:00' - timestamp '2001-09-27 12:00'</tt></td><td><tt class="LITERAL">interval '1 day 15:00:00'</tt></td></tr>
<tr><td><tt class="LITERAL">*</tt></td><td><tt class="LITERAL">900 * interval '1 second'</tt></td><td><tt class="LITERAL">interval '00:15:00'</tt></td></tr>
<tr><td><tt class="LITERAL">*</tt></td><td><tt class="LITERAL">21 * interval '1 day'</tt></td><td><tt class="LITERAL">interval '21 days'</tt></td></tr>
<tr><td><tt class="LITERAL">*</tt></td><td><tt class="LITERAL">double precision '3.5' * interval '1 hour'</tt></td><td><tt class="LITERAL">interval '03:30:00'</tt></td></tr>
<tr><td><tt class="LITERAL">/</tt></td><td><tt class="LITERAL">interval '1 hour' / double precision '1.5'</tt></td><td><tt class="LITERAL">interval '00:40:00'</tt></td></tr>
</tbody>
</table>
</div>
<a name="AEN11154"></a><a name="AEN11156"></a><a name="AEN11158"></a><a name="AEN11160"></a><a name="AEN11162"></a><a name="AEN11164"></a><a name="AEN11166"></a><a name="AEN11168"></a><a name="AEN11170"></a><a name="AEN11172"></a><a name="AEN11174"></a><a name="AEN11176"></a><a name="AEN11178"></a><a name="AEN11180"></a><a name="AEN11182"></a><a name="AEN11184"></a><a name="AEN11186"></a><a name="AEN11188"></a>
<div class="TABLE"><a name="FUNCTIONS-DATETIME-TABLE"></a>
<p><b>表9-26. 日期/时间函数</b></p>
<table border="1" class="CALSTABLE"><col><col><col><col><col>
<thead>
<tr><th>函数</th><th>返回类型</th><th>描述</th><th>例子</th><th>结果</th></tr>
</thead>
<tbody>
<tr><td><tt class="LITERAL"><code class="FUNCTION">age</code>(<tt class="TYPE">timestamp</tt>, <tt class="TYPE">timestamp</tt>)</tt></td><td><tt class="TYPE">interval</tt></td><td>减去参数后的"符号化"结果</td><td><tt class="LITERAL">age(timestamp '2001-04-10', timestamp '1957-06-13')</tt></td><td><tt class="LITERAL">43 years 9 mons 27 days</tt></td></tr>
<tr><td><tt class="LITERAL"><code class="FUNCTION">age</code>(<tt class="TYPE">timestamp</tt>)</tt></td><td><tt class="TYPE">interval</tt></td><td>从 <code class="FUNCTION">current_date</code> 减去参数后的结果</td><td><tt class="LITERAL">age(timestamp '1957-06-13')</tt></td><td><tt class="LITERAL">43 years 8 mons 3 days</tt></td></tr>
<tr><td><tt class="LITERAL"><code class="FUNCTION">clock_timestamp</code>()</tt></td><td><tt class="TYPE">timestamp with time zone</tt></td><td>实时时钟的当前时间戳；见<a href="functions-datetime.html#FUNCTIONS-DATETIME-CURRENT">节9.9.4</a></td><td>&nbsp;</td><td>&nbsp;</td></tr>
<tr><td><tt class="LITERAL"><code class="FUNCTION">current_date</code></tt></td><td><tt class="TYPE">date</tt></td><td>当前的日期；见<a href="functions-datetime.html#FUNCTIONS-DATETIME-CURRENT">节9.9.4</a></td><td>&nbsp;</td><td>&nbsp;</td></tr>
<tr><td><tt class="LITERAL"><code class="FUNCTION">current_time</code></tt></td><td><tt class="TYPE">time with time zone</tt></td><td>当日时间；见<a href="functions-datetime.html#FUNCTIONS-DATETIME-CURRENT">节9.9.4</a></td><td>&nbsp;</td><td>&nbsp;</td></tr>
<tr><td><tt class="LITERAL"><code class="FUNCTION">current_timestamp</code></tt></td><td><tt class="TYPE">timestamp with time zone</tt></td><td>当前事务开始时的时间戳；见<a href="functions-datetime.html#FUNCTIONS-DATETIME-CURRENT">节9.9.4</a></td><td>&nbsp;</td><td>&nbsp;</td></tr>
<tr><td><tt class="LITERAL"><code class="FUNCTION">date_part</code>(<tt class="TYPE">text</tt>, <tt class="TYPE">timestamp</tt>)</tt></td><td><tt class="TYPE">double precision</tt></td><td>获取子域(等效于 <code class="FUNCTION">extract</code>)；又见<a href="functions-datetime.html#FUNCTIONS-DATETIME-EXTRACT">节9.9.1</a></td><td><tt class="LITERAL">date_part('hour', timestamp '2001-02-16 20:38:40')</tt></td><td><tt class="LITERAL">20</tt></td></tr>
<tr><td><tt class="LITERAL"><code class="FUNCTION">date_part</code>(<tt class="TYPE">text</tt>, <tt class="TYPE">interval</tt>)</tt></td><td><tt class="TYPE">double precision</tt></td><td>获取子域(等效于 <code class="FUNCTION">extract</code>)；又见<a href="functions-datetime.html#FUNCTIONS-DATETIME-EXTRACT">节9.9.1</a></td><td><tt class="LITERAL">date_part('month', interval '2 years 3 months')</tt></td><td><tt class="LITERAL">3</tt></td></tr>
<tr><td><tt class="LITERAL"><code class="FUNCTION">date_trunc</code>(<tt class="TYPE">text</tt>, <tt class="TYPE">timestamp</tt>)</tt></td><td><tt class="TYPE">timestamp</tt></td><td>截断成指定的精度；又见<a href="functions-datetime.html#FUNCTIONS-DATETIME-TRUNC">节9.9.2</a></td><td><tt class="LITERAL">date_trunc('hour', timestamp '2001-02-16 20:38:40')</tt></td><td><tt class="LITERAL">2001-02-16 20:00:00</tt></td></tr>
<tr><td><tt class="LITERAL"><code class="FUNCTION">extract</code>(<tt class="PARAMETER">field</tt> from <tt class="TYPE">timestamp</tt>)</tt></td><td><tt class="TYPE">double precision</tt></td><td>获取子域；又见<a href="functions-datetime.html#FUNCTIONS-DATETIME-EXTRACT">节9.9.1</a></td><td><tt class="LITERAL">extract(hour from timestamp '2001-02-16 20:38:40')</tt></td><td><tt class="LITERAL">20</tt></td></tr>
<tr><td><tt class="LITERAL"><code class="FUNCTION">extract</code>(<tt class="PARAMETER">field</tt> from <tt class="TYPE">interval</tt>)</tt></td><td><tt class="TYPE">double precision</tt></td><td>获取子域；又见<a href="functions-datetime.html#FUNCTIONS-DATETIME-EXTRACT">节9.9.1</a></td><td><tt class="LITERAL">extract(month from interval '2 years 3 months')</tt></td><td><tt class="LITERAL">3</tt></td></tr>
<tr><td><tt class="LITERAL"><code class="FUNCTION">isfinite</code>(<tt class="TYPE">timestamp</tt>)</tt></td><td><tt class="TYPE">boolean</tt></td><td>测试是否为有穷时间戳</td><td><tt class="LITERAL">isfinite(timestamp '2001-02-16 21:28:30')</tt></td><td><tt class="LITERAL">true</tt></td></tr>
<tr><td><tt class="LITERAL"><code class="FUNCTION">isfinite</code>(<tt class="TYPE">interval</tt>)</tt></td><td><tt class="TYPE">boolean</tt></td><td>测试是否为有穷时间间隔</td><td><tt class="LITERAL">isfinite(interval '4 hours')</tt></td><td><tt class="LITERAL">true</tt></td></tr>
<tr><td><tt class="LITERAL"><code class="FUNCTION">justify_days</code>(<tt class="TYPE">interval</tt>)</tt></td><td><tt class="TYPE">interval</tt></td><td>按照每月 30 天调整时间间隔</td><td><tt class="LITERAL">justify_days(interval '30 days')</tt></td><td><tt class="LITERAL">1 month</tt></td></tr>
<tr><td><tt class="LITERAL"><code class="FUNCTION">justify_hours</code>(<tt class="TYPE">interval</tt>)</tt></td><td><tt class="TYPE">interval</tt></td><td>按照每天 24 小时调整时间间隔</td><td><tt class="LITERAL">justify_hours(interval '24 hours')</tt></td><td><tt class="LITERAL">1 day</tt></td></tr>
<tr><td><tt class="LITERAL"><code class="FUNCTION">justify_interval</code>(<tt class="TYPE">interval</tt>)</tt></td><td><tt class="TYPE">interval</tt></td><td>使用 <code class="FUNCTION">justify_days</code> 和 <code class="FUNCTION">justify_hours</code> 调整时间间隔的同时进行正负号调整</td><td><tt class="LITERAL">justify_interval(interval '1 mon -1 hour')</tt></td><td><tt class="LITERAL">29 days 23:00:00</tt></td></tr>
<tr><td><tt class="LITERAL"><code class="FUNCTION">localtime</code></tt></td><td><tt class="TYPE">time</tt></td><td>当日时间；见<a href="functions-datetime.html#FUNCTIONS-DATETIME-CURRENT">节9.9.4</a></td><td>&nbsp;</td><td>&nbsp;</td></tr>
<tr><td><tt class="LITERAL"><code class="FUNCTION">localtimestamp</code></tt></td><td><tt class="TYPE">timestamp</tt></td><td>当前事务开始时的时间戳；见<a href="functions-datetime.html#FUNCTIONS-DATETIME-CURRENT">节9.9.4</a></td><td>&nbsp;</td><td>&nbsp;</td></tr>
<tr><td><tt class="LITERAL"><code class="FUNCTION">now</code>()</tt></td><td><tt class="TYPE">timestamp with time zone</tt></td><td>当前事务开始时的时间戳；见<a href="functions-datetime.html#FUNCTIONS-DATETIME-CURRENT">节9.9.4</a></td><td>&nbsp;</td><td>&nbsp;</td></tr>
<tr><td><tt class="LITERAL"><code class="FUNCTION">statement_timestamp</code>()</tt></td><td><tt class="TYPE">timestamp with time zone</tt></td><td>实时时钟的当前时间戳；见<a href="functions-datetime.html#FUNCTIONS-DATETIME-CURRENT">节9.9.4</a></td><td>&nbsp;</td><td>&nbsp;</td></tr>
<tr><td><tt class="LITERAL"><code class="FUNCTION">timeofday</code>()</tt></td><td><tt class="TYPE">text</tt></td><td>与 <code class="FUNCTION">clock_timestamp</code> 相同，但结果是一个 <tt class="TYPE">text</tt> 字符串；见<a href="functions-datetime.html#FUNCTIONS-DATETIME-CURRENT">节9.9.4</a></td><td>&nbsp;</td><td>&nbsp;</td></tr>
<tr><td><tt class="LITERAL"><code class="FUNCTION">transaction_timestamp</code>()</tt></td><td><tt class="TYPE">timestamp with time zone</tt></td><td>当前事务开始时的时间戳；见<a href="functions-datetime.html#FUNCTIONS-DATETIME-CURRENT">节9.9.4</a></td><td>&nbsp;</td><td>&nbsp;</td></tr>
</tbody>
</table>
</div>
<p>除了这些函数以外，还支持 SQL 的 <tt class="LITERAL">OVERLAPS</tt> 操作符：</p>
<pre class="SYNOPSIS">(<tt class="REPLACEABLE"><i>start1</i></tt>, <tt class="REPLACEABLE"><i>end1</i></tt>) OVERLAPS (<tt class="REPLACEABLE"><i>start2</i></tt>, <tt class="REPLACEABLE"><i>end2</i></tt>)
(<tt class="REPLACEABLE"><i>start1</i></tt>, <tt class="REPLACEABLE"><i>length1</i></tt>) OVERLAPS (<tt class="REPLACEABLE"><i>start2</i></tt>, <tt class="REPLACEABLE"><i>length2</i></tt>)</pre>
<p>这个表达式在两个时间域(用它们的终点定义)重叠的时候生成真值。终点可以用一对日期、时间、时间戳来声明；或者是一个后面跟着一个时间间隔的日期、时间、时间戳。</p>
<pre class="SCREEN">SELECT (DATE '2001-02-16', DATE '2001-12-21') OVERLAPS
       (DATE '2001-10-30', DATE '2002-10-30');
<i class="LINEANNOTATION">Result: </i><samp class="COMPUTEROUTPUT">true</samp>
SELECT (DATE '2001-02-16', INTERVAL '100 days') OVERLAPS
       (DATE '2001-10-30', DATE '2002-10-30');
<i class="LINEANNOTATION">Result: </i><samp class="COMPUTEROUTPUT">false</samp></pre>
<p>当把 <tt class="TYPE">interval</tt> 值添加到 <tt class="TYPE">timestamp with time zone</tt> 上(或从中减去)的时候，days 部分会按照指定的天数增加(或减少) <tt class="TYPE">timestamp with time zone</tt> 的日期。对于横跨夏令时的变化(会话的时区设置被识别为夏时制)，<tt class="LITERAL">interval '1 day'</tt> 并不一定等于 <tt class="LITERAL">interval '24 hours'</tt> 。例如，当会话的时区设置为 <tt class="LITERAL">CST7CDT</tt> 的时候，<tt class="LITERAL">timestamp with time zone '2005-04-02 12:00-07' + interval '1 day' </tt> 的结果是 <tt class="LITERAL">timestamp with time zone '2005-04-03 12:00-06'</tt> ，而将 <tt class="LITERAL">interval '24 hours'</tt> 增加到相同的 <tt class="TYPE">timestamp with time zone</tt> 之上的结果则是 <tt class="LITERAL">timestamp with time zone '2005-04-03 13:00-06'</tt> ，因为 <tt class="LITERAL">CST7CDT</tt> 时区在 <tt class="LITERAL">2005-04-03 02:00</tt> 的时候有一个夏令时变更。</p>
<div class="SECT2"><h2 class="SECT2"><a name="FUNCTIONS-DATETIME-EXTRACT">9.9.1. <code class="FUNCTION">EXTRACT</code>, <code class="FUNCTION">date_part</code></a></h2><a name="AEN11499"></a><a name="AEN11501"></a>
<pre class="SYNOPSIS">EXTRACT(<tt class="REPLACEABLE"><i>field</i></tt> FROM <tt class="REPLACEABLE"><i>source</i></tt>)</pre>
<p><code class="FUNCTION">extract</code> 函数从日期/时间数值里抽取子域，比如年、小时等。<tt class="REPLACEABLE"><i>source</i></tt> 必须是一个 <tt class="TYPE">timestamp</tt>, <tt class="TYPE">time</tt>, <tt class="TYPE">interval</tt> 类型的值表达式(类型为 <tt class="TYPE">date</tt> 的表达式将转换为 <tt class="TYPE">timestamp</tt> ，因此也可以用)。<tt class="REPLACEABLE"><i>field</i></tt> 是一个标识符或者字符串，它指定从源数据中抽取的域。<code class="FUNCTION">extract</code> 函数返回类型为 <tt class="TYPE">double precision</tt> 的数值。下列数值是有效数据域的名字：</p>
<div class="VARIABLELIST">
<dl>
<dt><tt class="LITERAL">century</tt></dt>
<dd><p>世纪</p>
<pre class="SCREEN">SELECT EXTRACT(CENTURY FROM TIMESTAMP '2000-12-16 12:21:13');
<i class="LINEANNOTATION">Result: </i><samp class="COMPUTEROUTPUT">20</samp>
SELECT EXTRACT(CENTURY FROM TIMESTAMP '2001-02-16 20:38:40');
<i class="LINEANNOTATION">Result: </i><samp class="COMPUTEROUTPUT">21</samp></pre>
<p>第一个世纪从 0001-01-01 00:00:00 AD 开始，尽管那时候人们还不知道这是第一个世纪。这个定义适用于所有使用阳历的国家。没有 0 世纪，我们直接从公元前 1 世纪到公元 1 世纪。如果你认为这个不合理，那么请把抱怨发给：梵蒂冈，罗马圣彼得教堂，教皇收。</p>
<p>PostgreSQL 8.0 以前版本里并不遵循世纪的习惯编号，只是把年份除以 100 。</p></dd>
<dt><tt class="LITERAL">day</tt></dt>
<dd><p>(月份)里的日期(1-31)</p>
<pre class="SCREEN">SELECT EXTRACT(DAY FROM TIMESTAMP '2001-02-16 20:38:40');
<i class="LINEANNOTATION">Result: </i><samp class="COMPUTEROUTPUT">16</samp></pre></dd>
<dt><tt class="LITERAL">decade</tt></dt>
<dd><p>年份除以 10</p>
<pre class="SCREEN">SELECT EXTRACT(DECADE FROM TIMESTAMP '2001-02-16 20:38:40');
<i class="LINEANNOTATION">Result: </i><samp class="COMPUTEROUTPUT">200</samp></pre></dd>
<dt><tt class="LITERAL">dow</tt></dt>
<dd><p>每周的星期号(0-6 ；星期天是 0)(仅用于 <tt class="TYPE">timestamp</tt> 值)</p>
<pre class="SCREEN">SELECT EXTRACT(DOW FROM TIMESTAMP '2001-02-16 20:38:40');
<i class="LINEANNOTATION">Result: </i><samp class="COMPUTEROUTPUT">5</samp></pre>
<p>请注意，<code class="FUNCTION">extract</code> 的星期几编号和 <code class="FUNCTION">to_char</code> 函数不同。</p></dd>
<dt><tt class="LITERAL">doy</tt></dt>
<dd><p>一年的第几天(1-365/366)(仅用于 <tt class="TYPE">timestamp</tt> 值)</p>
<pre class="SCREEN">SELECT EXTRACT(DOY FROM TIMESTAMP '2001-02-16 20:38:40');
<i class="LINEANNOTATION">Result: </i><samp class="COMPUTEROUTPUT">47</samp></pre></dd>
<dt><tt class="LITERAL">epoch</tt></dt>
<dd><p>对于 <tt class="TYPE">date</tt> 和 <tt class="TYPE">timestamp</tt> 值而言，是自 1970-01-01 00:00:00-00 以来的秒数(结果可能是负数)；对于 <tt class="TYPE">interval</tt> 值而言，它是时间间隔的总秒数。</p>
<pre class="SCREEN">SELECT EXTRACT(EPOCH FROM TIMESTAMP WITH TIME ZONE '2001-02-16 20:38:40-08');
<i class="LINEANNOTATION">Result: </i><samp class="COMPUTEROUTPUT">982384720</samp>

SELECT EXTRACT(EPOCH FROM INTERVAL '5 days 3 hours');
<i class="LINEANNOTATION">Result: </i><samp class="COMPUTEROUTPUT">442800</samp></pre>
<p>下面是把 epoch 值转换回时间戳的方法：</p>
<pre class="SCREEN">SELECT TIMESTAMP WITH TIME ZONE 'epoch' + 982384720 * INTERVAL '1 second';</pre></dd>
<dt><tt class="LITERAL">hour</tt></dt>
<dd><p>小时域(0-23)</p>
<pre class="SCREEN">SELECT EXTRACT(HOUR FROM TIMESTAMP '2001-02-16 20:38:40');
<i class="LINEANNOTATION">Result: </i><samp class="COMPUTEROUTPUT">20</samp></pre></dd>
<dt><tt class="LITERAL">microseconds</tt></dt>
<dd><p>秒域(包括小数部分)乘以 1,000,000 。请注意它包括全部的秒。</p>
<pre class="SCREEN">SELECT EXTRACT(MICROSECONDS FROM TIME '17:12:28.5');
<i class="LINEANNOTATION">Result: </i><samp class="COMPUTEROUTPUT">28500000</samp></pre></dd>
<dt><tt class="LITERAL">millennium</tt></dt>
<dd><p>千年</p>
<pre class="SCREEN">SELECT EXTRACT(MILLENNIUM FROM TIMESTAMP '2001-02-16 20:38:40');
<i class="LINEANNOTATION">Result: </i><samp class="COMPUTEROUTPUT">3</samp></pre>
<p>20 世纪(19xx 年)里面的年份在第二个千年里。第三个千年从 2001 年 1 月 1 日零时开始。</p>
<p>PostgreSQL 8.0 之前的版本并不遵循前年编号的习惯，只是返回年份除以 1000 。</p></dd>
<dt><tt class="LITERAL">milliseconds</tt></dt>
<dd><p>秒域(包括小数部分)乘以 1000 。请注意它包括完整的秒。</p>
<pre class="SCREEN">SELECT EXTRACT(MILLISECONDS FROM TIME '17:12:28.5');
<i class="LINEANNOTATION">Result: </i><samp class="COMPUTEROUTPUT">28500</samp></pre></dd>
<dt><tt class="LITERAL">minute</tt></dt>
<dd><p>分钟域(0-59)</p>
<pre class="SCREEN">SELECT EXTRACT(MINUTE FROM TIMESTAMP '2001-02-16 20:38:40');
<i class="LINEANNOTATION">Result: </i><samp class="COMPUTEROUTPUT">38</samp></pre></dd>
<dt><tt class="LITERAL">month</tt></dt>
<dd><p>对于 <tt class="TYPE">timestamp</tt> 值，它是一年里的月份数(1-12)；对于 <tt class="TYPE">interval</tt> 值，它是月的数目，然后对 12 取模(0-11)</p>
<pre class="SCREEN">SELECT EXTRACT(MONTH FROM TIMESTAMP '2001-02-16 20:38:40');
<i class="LINEANNOTATION">Result: </i><samp class="COMPUTEROUTPUT">2</samp>

SELECT EXTRACT(MONTH FROM INTERVAL '2 years 3 months');
<i class="LINEANNOTATION">Result: </i><samp class="COMPUTEROUTPUT">3</samp>

SELECT EXTRACT(MONTH FROM INTERVAL '2 years 13 months');
<i class="LINEANNOTATION">Result: </i><samp class="COMPUTEROUTPUT">1</samp></pre></dd>
<dt><tt class="LITERAL">quarter</tt></dt>
<dd><p>该天所在的该年的季度(1-4)(仅用于 <tt class="TYPE">timestamp</tt> 值)</p>
<pre class="SCREEN">SELECT EXTRACT(QUARTER FROM TIMESTAMP '2001-02-16 20:38:40');
<i class="LINEANNOTATION">Result: </i><samp class="COMPUTEROUTPUT">1</samp></pre></dd>
<dt><tt class="LITERAL">second</tt></dt>
<dd><p>秒域，包括小数部分(0-59)<a name="AEN11654" href="functions-datetime.html#FTN.AEN11654"><span class="footnote">[1]</span></a></p>
<pre class="SCREEN">SELECT EXTRACT(SECOND FROM TIMESTAMP '2001-02-16 20:38:40');
<i class="LINEANNOTATION">Result: </i><samp class="COMPUTEROUTPUT">40</samp>

SELECT EXTRACT(SECOND FROM TIME '17:12:28.5');
<i class="LINEANNOTATION">Result: </i><samp class="COMPUTEROUTPUT">28.5</samp></pre></dd>
<dt><tt class="LITERAL">timezone</tt></dt>
<dd><p>与 UTC 的时区偏移量，以秒记。正数对应 UTC 东边的时区，负数对应 UTC 西边的时区。</p></dd>
<dt><tt class="LITERAL">timezone_hour</tt></dt>
<dd><p>时区偏移量的小时部分。</p></dd>
<dt><tt class="LITERAL">timezone_minute</tt></dt>
<dd><p>时区偏移量的分钟部分。</p></dd>
<dt><tt class="LITERAL">week</tt></dt>
<dd><p>该天在所在的年份里是第几周。ISO-8601 定义一年的第一周包含该年的一月四日(ISO-8601 的周从星期一开始)。换句话说，一年的第一个星期四在第一周。(只用于 <tt class="TYPE">timestamp</tt> 值)</p>
<p>因此，一月的头几天可能是前一年的第 52 或者第 53 周。比如，<tt class="LITERAL">2005-01-01</tt> 是 2004 年的第 53 周，而 <tt class="LITERAL">2006-01-01</tt> 是 2005 年的第 52 周。</p>
<pre class="SCREEN">SELECT EXTRACT(WEEK FROM TIMESTAMP '2001-02-16 20:38:40');
<i class="LINEANNOTATION">Result: </i><samp class="COMPUTEROUTPUT">7</samp></pre></dd>
<dt><tt class="LITERAL">year</tt></dt>
<dd><p>年份域。要记住这里没有 <tt class="LITERAL">0 AD</tt> ，所以从 <tt class="LITERAL">AD</tt> 年里抽取 <tt class="LITERAL">BC</tt> 年应该小心些。</p>
<pre class="SCREEN">SELECT EXTRACT(YEAR FROM TIMESTAMP '2001-02-16 20:38:40');
<i class="LINEANNOTATION">Result: </i><samp class="COMPUTEROUTPUT">2001</samp></pre></dd>
</dl>
</div>
<p><code class="FUNCTION">extract</code> 函数主要的用途是运算。对于用于显示的日期/时间数值格式化，参阅<a href="functions-formatting.html">节9.8</a>。</p>
<p><code class="FUNCTION">date_part</code> 函数是在传统的 Ingres 函数的基础上制作的(该函数等效于 SQL 标准函数 <code class="FUNCTION">extract</code>)：</p>
<pre class="SYNOPSIS">date_part('<tt class="REPLACEABLE"><i>field</i></tt>', <tt class="REPLACEABLE"><i>source</i></tt>)</pre>
<p>请注意这里的 <tt class="REPLACEABLE"><i>field</i></tt> 参数必须是一个字符串值，而不是一个名字。有效的 <code class="FUNCTION">date_part</code> 数域名和 <code class="FUNCTION">extract</code> 是一样的。</p>
<pre class="SCREEN">SELECT date_part('day', TIMESTAMP '2001-02-16 20:38:40');
<i class="LINEANNOTATION">Result: </i><samp class="COMPUTEROUTPUT">16</samp>

SELECT date_part('hour', INTERVAL '4 hours 3 minutes');
<i class="LINEANNOTATION">Result: </i><samp class="COMPUTEROUTPUT">4</samp></pre>
</div>
<div class="SECT2"><h2 class="SECT2"><a name="FUNCTIONS-DATETIME-TRUNC">9.9.2. <code class="FUNCTION">date_trunc</code></a></h2><a name="AEN11723"></a>
<p><code class="FUNCTION">date_trunc</code> 函数在概念上和用于数字的 <code class="FUNCTION">trunc</code> 函数类似。</p>
<pre class="SYNOPSIS">date_trunc('<tt class="REPLACEABLE"><i>field</i></tt>', <tt class="REPLACEABLE"><i>source</i></tt>)</pre>
<p><tt class="REPLACEABLE"><i>source</i></tt> 是 <tt class="TYPE">timestamp</tt> 或 <tt class="TYPE">interval</tt> 类型的值表达式(<tt class="TYPE">date</tt> 和 <tt class="TYPE">time</tt> 类型的值都分别自动转换成 <tt class="TYPE">timestamp</tt> 或 <tt class="TYPE">interval</tt>)。用 <tt class="REPLACEABLE"><i>field</i></tt> 选择对该时间戳值用什么样的精度进行截断。返回的数值是 <tt class="TYPE">timestamp</tt> 或 <tt class="TYPE">interval</tt> 类型，所有小于选定的精度的域都设置为零(日期和月份域则为 1)。</p>
<p><tt class="REPLACEABLE"><i>field</i></tt> 的有效数值是：
<table border="0">
<tbody>
<tr><td><tt class="LITERAL">microseconds</tt></td></tr>
<tr><td><tt class="LITERAL">milliseconds</tt></td></tr>
<tr><td><tt class="LITERAL">second</tt></td></tr>
<tr><td><tt class="LITERAL">minute</tt></td></tr>
<tr><td><tt class="LITERAL">hour</tt></td></tr>
<tr><td><tt class="LITERAL">day</tt></td></tr>
<tr><td><tt class="LITERAL">week</tt></td></tr>
<tr><td><tt class="LITERAL">month</tt></td></tr>
<tr><td><tt class="LITERAL">quarter</tt></td></tr>
<tr><td><tt class="LITERAL">year</tt></td></tr>
<tr><td><tt class="LITERAL">decade</tt></td></tr>
<tr><td><tt class="LITERAL">century</tt></td></tr>
<tr><td><tt class="LITERAL">millennium</tt></td></tr>
</tbody>
</table></P>
<p>例子：</p>
<pre class="SCREEN">SELECT date_trunc('hour', TIMESTAMP '2001-02-16 20:38:40');
<i class="LINEANNOTATION">Result: </i><samp class="COMPUTEROUTPUT">2001-02-16 20:00:00</samp>

SELECT date_trunc('year', TIMESTAMP '2001-02-16 20:38:40');
<i class="LINEANNOTATION">Result: </i><samp class="COMPUTEROUTPUT">2001-01-01 00:00:00</samp></pre>
</div>
<div class="SECT2"><h2 class="SECT2"><a name="FUNCTIONS-DATETIME-ZONECONVERT">9.9.3. <tt class="LITERAL">AT TIME ZONE</tt></a></h2><a name="AEN11780"></a><a name="AEN11783"></a>
<p><tt class="LITERAL">AT TIME ZONE</tt> 构造允许把时间戳转换成不同的时区。<a href="functions-datetime.html#FUNCTIONS-DATETIME-ZONECONVERT-TABLE">表9-27</a>显示了其变体。</p>
<div class="TABLE"><a name="FUNCTIONS-DATETIME-ZONECONVERT-TABLE"></a>
<p><b>表9-27. <tt class="LITERAL">AT TIME ZONE</tt> 变体</b></p>
<table border="1" class="CALSTABLE"><col><col><col>
<thead>
<tr><th>表达式</th><th>返回类型</th><th>描述</th></tr>
</thead>
<tbody>
<tr><td><tt class="LITERAL"><tt class="TYPE">timestamp without time zone</tt> AT TIME ZONE <tt class="REPLACEABLE"><i>zone</i></tt></tt></td><td><tt class="TYPE">timestamp with time zone</tt></td><td>把给出的<span class="emphasis"><i class="EMPHASIS">不带时区</i></span>的时间戳转换成给定时区的时间戳</td></tr>
<tr><td><tt class="LITERAL"><tt class="TYPE">timestamp with time zone</tt> AT TIME ZONE <tt class="REPLACEABLE"><i>zone</i></tt></tt></td><td><tt class="TYPE">timestamp without time zone</tt></td><td>把给出的<span class="emphasis"><i class="EMPHASIS">带时区</i></span>的时间戳转换成给定时区的时间戳</td></tr>
<tr><td><tt class="LITERAL"><tt class="TYPE">time with time zone</tt> AT TIME ZONE <tt class="REPLACEABLE"><i>zone</i></tt></tt></td><td><tt class="TYPE">time with time zone</tt></td><td>把给出的<span class="emphasis"><i class="EMPHASIS">带时区</i></span>的时间转换成给定时区的时间</td></tr>
</tbody>
</table>
</div>
<p>在这些表达式里，<tt class="REPLACEABLE"><i>zone</i></tt> 可以声明为文本串(比如 <tt class="LITERAL">'PST'</tt>)或者一个时间间隔(比如 <tt class="LITERAL">INTERVAL '-08:00'</tt>)。在文本的情况下，可用的时区名字在<a href="datatype-datetime.html#DATATYPE-TIMEZONES">节8.5.3</a>有详细描述。</p>
<p>例子(假设本地时区是 <tt class="LITERAL">PST8PDT</tt>)：</p>
<pre class="SCREEN">SELECT TIMESTAMP '2001-02-16 20:38:40' AT TIME ZONE 'MST';
<i class="LINEANNOTATION">Result: </i><samp class="COMPUTEROUTPUT">2001-02-16 19:38:40-08</samp>

SELECT TIMESTAMP WITH TIME ZONE '2001-02-16 20:38:40-05' AT TIME ZONE 'MST';
<i class="LINEANNOTATION">Result: </i><samp class="COMPUTEROUTPUT">2001-02-16 18:38:40</samp></pre>
<p>第一个例子接受一个无时区的时间戳然后把它解释成 MST(UTC-7) 时间生成 UTC 时间戳，然后把这个时间转换为 PST(UTC-8) 显示。第二个例子接受一个声明为 EST(UTC-5) 的时间戳，然后把它转换成 MST(UTC-7) 的当地时间。</p>
<p><tt class="LITERAL"><code class="FUNCTION">timezone</code>(<tt class="REPLACEABLE"><i>zone</i></tt>, <tt class="REPLACEABLE"><i>timestamp</i></tt>)</tt> 函数等效于 SQL 兼容的构造 <tt class="LITERAL"><tt class="REPLACEABLE"><i>timestamp</i></tt> AT TIME ZONE <tt class="REPLACEABLE"><i>zone</i></tt></tt></p>
</div>
<div class="SECT2"><h2 class="SECT2"><a name="FUNCTIONS-DATETIME-CURRENT">9.9.4. 当前日期/时间</a></h2><a name="AEN11847"></a><a name="AEN11850"></a>
<p>PostgreSQL 提供许多返回当前日期和时间的函数。这些符合 SQL 标准的函数全部都按照当前事务的开始时刻返回结果：</p>
<pre class="SYNOPSIS">CURRENT_DATE
CURRENT_TIME
CURRENT_TIMESTAMP
CURRENT_TIME(<tt class="REPLACEABLE"><i>precision</i></tt>)
CURRENT_TIMESTAMP(<tt class="REPLACEABLE"><i>precision</i></tt>)
LOCALTIME
LOCALTIMESTAMP
LOCALTIME(<tt class="REPLACEABLE"><i>precision</i></tt>)
LOCALTIMESTAMP(<tt class="REPLACEABLE"><i>precision</i></tt>)</pre>
<p><code class="FUNCTION">CURRENT_TIME</code> 和 <code class="FUNCTION">CURRENT_TIMESTAMP</code> 返回带有时区的值；<code class="FUNCTION">LOCALTIME</code> 和 <code class="FUNCTION">LOCALTIMESTAMP</code> 返回不带时区的值。</p>
<p><code class="FUNCTION">CURRENT_TIME</code>, <code class="FUNCTION">CURRENT_TIMESTAMP</code>, <code class="FUNCTION">LOCALTIME</code>, <code class="FUNCTION">LOCALTIMESTAMP</code> 可以有选择地给予一个精度参数，该精度导致结果的秒数域园整到指定小数位。如果没有精度参数，将给予所能得到的全部精度。</p>
<p>一些例子：</p>
<pre class="SCREEN">SELECT CURRENT_TIME;
<i class="LINEANNOTATION">Result: </i><samp class="COMPUTEROUTPUT">14:39:53.662522-05</samp>

SELECT CURRENT_DATE;
<i class="LINEANNOTATION">Result: </i><samp class="COMPUTEROUTPUT">2001-12-23</samp>

SELECT CURRENT_TIMESTAMP;
<i class="LINEANNOTATION">Result: </i><samp class="COMPUTEROUTPUT">2001-12-23 14:39:53.662522-05</samp>

SELECT CURRENT_TIMESTAMP(2);
<i class="LINEANNOTATION">Result: </i><samp class="COMPUTEROUTPUT">2001-12-23 14:39:53.66-05</samp>

SELECT LOCALTIMESTAMP;
<i class="LINEANNOTATION">Result: </i><samp class="COMPUTEROUTPUT">2001-12-23 14:39:53.662522</samp></pre>
<p>因为这些函数全部都按照当前事务的开始时刻返回结果，所以它们的值在事务运行的整个期间内都不改变。我们认为这是一个特性：目的是为了允许一个事务在"当前时间"上有连贯的概念，这样在同一个事务里的多个修改可以保持同样的时间戳。</p>
<div class="NOTE">
<blockquote class="NOTE">
<p><b>【注意】</b>许多其它数据库系统更频繁地更新这些数值。</p>
</blockquote>
</div>
<p>PostgreSQL 同样也提供了返回实时时间值的函数，它们的返回值会在事务中随时间的前进而变化。这些不附合 SQL 标准的函数列表如下：</p>
<pre class="SYNOPSIS">now()
transaction_timestamp()
statement_timestamp()
clock_timestamp()
timeofday()</pre>
<p><code class="FUNCTION">now()</code> 是传统的 PostgreSQL 和 <code class="FUNCTION">CURRENT_TIMESTAMP</code> 等效的函数。<code class="FUNCTION">transaction_timestamp()</code> 等效于 <code class="FUNCTION">CURRENT_TIMESTAMP</code> ，不过其命名准确的表明了其含义。<code class="FUNCTION">statement_timestamp()</code> 返回当前事务开始时刻的时间戳(更准确的说是收到客户端最后一条命令的时间)。<code class="FUNCTION">statement_timestamp()</code> 和 <code class="FUNCTION">transaction_timestamp()</code> 在一个事务的第一条命令里返回值相同，但是在随后的命令中却不一定相同。<code class="FUNCTION">clock_timestamp()</code> 返回实时时钟的当前时间戳，因此它的值甚至在同一条 SQL 命令中都会变化。<code class="FUNCTION">timeofday()</code> 相当于 <code class="FUNCTION">clock_timestamp()</code> ，也返回实时时钟的当前时间戳，由于历史原因，它返回一个 <tt class="TYPE">text</tt> 字符串，而不是 <tt class="TYPE">timestamp with time zone</tt> 值。</p>
<p>所有日期/时间类型还接受特殊的文本值 <tt class="LITERAL">now</tt> ，用于声明当前的日期和时间(重申：当前事务的开始时刻)。因此，下面三个都返回相同的结果：</p>
<pre class="PROGRAMLISTING">SELECT CURRENT_TIMESTAMP;
SELECT now();
SELECT TIMESTAMP 'now';  -- incorrect for use with DEFAULT</pre>
<div class="TIP">
<blockquote class="TIP">
<p><b>【提示】</b>在创建表的时候你不应该用第三种形式声明一个 <tt class="LITERAL">DEFAULT</tt> 值。系统将在分析这个常量的时候把 <tt class="LITERAL">now</tt> 转换为一个 <tt class="TYPE">timestamp</tt> ，因此这个缺省值就会变成创建表的时间！而前两种形式要到实际使用缺省值的时候才计算，因为它们是函数调用。因此它们可以给出每次插入行的时刻。</p>
</blockquote>
</div>
</div>
<div class="SECT2"><h2 class="SECT2"><a name="FUNCTIONS-DATETIME-DELAY">9.9.5. 延时执行</a></h2><a name="AEN11914"></a><a name="AEN11916"></a><a name="AEN11918"></a>
<p>下面的这个函数可以用于让服务器进程延时执行：</p>
<pre class="SYNOPSIS">pg_sleep(<tt class="REPLACEABLE"><i>seconds</i></tt>)</pre>
<p><code class="FUNCTION">pg_sleep</code> 让当前的会话进程休眠 <tt class="REPLACEABLE"><i>seconds</i></tt> 秒以后再执行。<tt class="REPLACEABLE"><i>seconds</i></tt> 是一个 <tt class="TYPE">double precision</tt> 类型的值，所以可以指定带小数的秒数。例如：</p>
<pre class="PROGRAMLISTING">SELECT pg_sleep(1.5);</pre>
<div class="NOTE">
<blockquote class="NOTE">
<p><b>【注意】</b>有效的休眠时间间隔精度是平台相关的，通常 0.01 秒是通用的。休眠的时间将至少等于指定的时间，也有可能由于服务器荷载较重等原因而比指定的时间长。</p>
</blockquote>
</div>
<div class="WARNING">
<table class="WARNING" border="1" width="100%">
<tr><td align="CENTER"><b>警告</b></td></tr>
<tr><td align="LEFT"><p>请确保调用 <code class="FUNCTION">pg_sleep</code> 的会话没有持有不必要的锁。否则其它会话可能必须等待这个休眠的会话释放所持有的锁，从而减慢系统速度。</p></td></tr>
</table>
</div>
</div>
</div>
<h3 class="FOOTNOTES">注意</h3>
<table border="0" class="FOOTNOTES" width="100%">
<tr><td align="LEFT" valign="TOP" width="5%"><a name="FTN.AEN11654" href="functions-datetime.html#AEN11654"><span class="footnote">[1]</span></a></td><td align="LEFT" valign="TOP" width="95%"><p>如果操作系统实现了润秒，那么上限是 60 。</p></td></tr>
</table>
<div>
<hr align="LEFT" width="100%">
<table summary="Footer navigation table" width="100%" border="0" cellpadding="0" cellspacing="0">
<tr><td width="33%" align="left" valign="top"><a href="functions-formatting.html" accesskey="P">后退</a></td><td width="34%" align="center" valign="top"><a href="index.html" accesskey="H">首页</a></td><td width="33%" align="right" valign="top"><a href="functions-geometry.html" accesskey="N">前进</a></td></tr>
<tr><td width="33%" align="left" valign="top">数据类型格式化函数</td><td width="34%" align="center" valign="top"><a href="functions.html" accesskey="U">上一级</a></td><td width="33%" align="right" valign="top">几何函数和操作符</td></tr>
</table>
</div>
</body></html>